package com.cib.icarus.core.enums;

import com.cib.icarus.core.utils.ByteUtils;
import com.cib.icarus.core.utils.internals.StrUtils;
import com.google.common.io.BaseEncoding;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.*;


/**
 * @author goomba
 */
public enum IcarusHashEnum {

    /**
     * 算法名称：md5 摘要长度（位）：128 输出字段长度(字节)：16 安全性：安全 用途描述：数据完整性验证、密码存储等
     */
    MD5("md5", 128, new MD5Digest()),
    /**
     * 算法名称：sha1 摘要长度（位）：160 输出字段长度(字节)：20 安全性：不安全 用途描述：数据完整性验证、密码存储等
     */
    SHA1("sha1", 160, new SHA1Digest()),

    /**
     * 算法名称：sha224 摘要长度（位）：224 输出字段长度(字节)：28 安全性：低 用途描述：数据完整性验证、密码存储等
     */
    SHA2_224("sha-224", 224, new SHA224Digest()),

    /**
     * 算法名称：sha256 摘要长度（位）：256 输出字段长度(字节)：32 安全性：中等 用途描述：数据完整性验证、数字签名等
     */
    SHA2_256("sha-256", 256, new SHA256Digest()),

    /**
     * 算法名称：sha384 摘要长度（位）：384 输出字段长度(字节)：48 安全性：高 用途描述：数字签名、加密算法等
     */
    SHA2_384("sha-384", 384, new SHA384Digest()),
    /**
     * 算法名称：sha512 摘要长度（位）：512 输出字段长度(字节)：64 安全性：高 用途描述：数字签名、加密算法等
     */
    SHA2_512("sha-512", 512, new SHA512Digest()),

    /**
     * 算法名称：sha3-224 摘要长度（位）：224 输出字段长度(字节)：28 安全性：高 用途描述：未来标准的 SHA-3 家族成员，适用于数字签名等
     */
    SHA3_224("sha3-224", 224, new SHA3Digest(224)),
    /**
     * 算法名称：sha3-256 摘要长度（位）：256 输出字段长度(字节)：32 安全性：高 用途描述：未来标准的 SHA-3 家族成员，适用于数字签名等
     */
    SHA3_256("sha3-256", 256, new SHA3Digest(256)),
    /**
     * 算法名称：sha3-384 摘要长度（位）：384 输出字段长度(字节)：48 安全性：高 用途描述：未来标准的 SHA-3 家族成员，适用于数字签名等
     */
    SHA3_384("sha3-384", 384, new SHA3Digest(384)),
    /**
     * 算法名称：sha3-512 摘要长度（位）：512 输出字段长度(字节)：64 安全性：高 用途描述：未来标准的 SHA-3 家族成员，适用于数字签名等
     */
    SHA3_512("sha3-512", 512, new SHA3Digest(512)),

    ;

    private final String algorithm;

    private final Integer bitLength;

    private final Digest digest;

    IcarusHashEnum(String algorithm, Integer bitLength, Digest digest) {
        this.algorithm = algorithm;
        this.bitLength = bitLength;
        this.digest = digest;
    }

    /**
     * 将字符串进行哈希处理并返回十六进制表示
     * 如果输入字符串为空或空白，则直接返回原字符串
     * 此方法主要用于提供字符串的哈希值，以便于数据校验或存储优化
     *
     * @param target 待处理的字符串
     * @return 处理后的十六进制字符串如果输入为空或空白，则返回原字符串
     */
    public String hashHexStr(String target) {
        if (StrUtils.isBlank(target)) {
            return target;
        }
        byte[] rsData = handler(target);
        return ByteUtils.arrayToHexString(rsData);
    }


    public int hashHexStrLength() {
        return this.bitLength / 8 * 2;
    }

    /**
     * 将输入字符串进行哈希并返回Base64编码的结果
     * 如果输入字符串为空或null，则直接返回原字符串
     *
     * @param target 待处理的字符串
     * @return 处理后的Base64编码字符串
     */
    public String hashBase64Str(String target) {
        if (StrUtils.isBlank(target)) {
            return target;
        }
        byte[] rsData = handler(target);
        return BaseEncoding.base64().encode(rsData);
    }

    public int hashBase64StrLength() {
        int charLength = bitLength / 8;
        charLength = charLength % 3 == 0 ? charLength : (charLength + (3 - charLength % 3));
        return charLength / 3 * 4;
    }

    public String getAlgorithm() {
        return algorithm;
    }

    private byte[] handler(String target) {
        digest.update(target.getBytes(), 0, target.getBytes().length);
        byte[] rsData = new byte[digest.getDigestSize()];
        digest.doFinal(rsData, 0);
        return rsData;
    }

}
